package com.hmy.common.timer.retry;

import com.hmy.common.timer.Timeout;
import com.hmy.common.timer.Timer;
import com.hmy.common.timer.TimerTask;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class AbstractRetryTimeTask implements TimerTask {

    /**
     * 重试次数
     */
    public int retryTimes;

    /**
     * 任务名称
     */
    public String taskName;

    /**
     * 重试的间隔时间
     */
    public long delay;

    /**
     * 重试的间隔时间单位
     */
    public TimeUnit delayUnit;

    /**
     * 已经运行的次数
     */
    private int times = 0;

    /**
     * 用于默认的任务名称后的索引
     */
    private static final AtomicInteger taskNum = new AtomicInteger();

    /**
     * 默认的重试次数 3次
     */
    private static final int DEFAULT_RETRY_TIME = 3;

    /**
     * 默认重试间隔 1分钟
     */
    private static final long DEFAULT_RETRY_DELAY = 2;

    /**
     * 默认重试间隔时间单位 分钟
     */
    private static final TimeUnit DEFAULT_DELAY_UNIT = TimeUnit.SECONDS;

    public void setRetryTimes(int retryTimes) {
        this.retryTimes = retryTimes;
    }

    public void setTaskName(String taskName) {
        this.taskName = taskName;
    }

    public void setDelay(long delay) {
        this.delay = delay;
    }

    public void setDelayUnit(TimeUnit delayUnit) {
        this.delayUnit = delayUnit;
    }

    public AbstractRetryTimeTask() {
        this.retryTimes = DEFAULT_RETRY_TIME;
        this.taskName = "task-" + taskNum.incrementAndGet();
        this.delay = DEFAULT_RETRY_DELAY;
        this.delayUnit = DEFAULT_DELAY_UNIT;
    }

    //    public AbstractRetryTimeTask() {
//        this(DEFAULT_RETRY_TIME, "task-" + taskNum.incrementAndGet());
//    }
//
//    public AbstractRetryTimeTask(int retryTimes, String taskName) {
//        this(retryTimes, taskName, DEFAULT_RETRY_DELAY, DEFAULT_DELAY_UNIT);
//    }
//
//    public AbstractRetryTimeTask(int retryTimes, String taskName, long delay, TimeUnit delayUnit) {
//        this.retryTimes = retryTimes;
//        this.taskName = taskName;
//        this.delay = delay;
//        this.delayUnit = delayUnit;
//    }



    @Override
    public void run(Timeout timeout) throws Exception {
        if (times > retryTimes) {
            System.out.printf("任务：{%s}已经重试了{%s}次，不再重试\n", this.taskName, this.times - 1);
            return;
        }
        try {
            doSome();
        } catch (Throwable t) {
            if (times == 0) {
                System.out.printf("任务:{%s}执行失败，报错：\n{%s}", taskName, ExceptionUtils.getStackTrace(t));
            } else {
                System.out.printf("任务:{%s}在重试第{%d}次后执行失败，报错：\n{%s}", taskName, times, ExceptionUtils.getStackTrace(t));
            }
            times++;
            reput(timeout);
        }
    }

    /**
     * 将任务添加至时间轮重新执行
     *
     * @param timeout 任务信息
     */
    private void reput(Timeout timeout) {
        Timer timer = timeout.timer();
        timer.newTimeout(timeout.task(), delay, delayUnit);
    }

    protected abstract void doSome();

}
